#include "user_service.hpp"
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <sstream>
#include <iomanip>
#include "../core/di_container.hpp"
#include "../common/logger.hpp"

namespace service {

UserService::UserService() {
    Logger::info("UserService created");
    user_storage_ = DIContainer::get<storage::IUserStorage>();
}

UserService::~UserService() {
    Logger::info("UserService destroyed");
}

std::string UserService::hash_password(const std::string& password) {
    // 使用OpenSSL 3.0的EVP接口计算SHA256哈希
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hash_len;

    // 创建消息摘要上下文
    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
    if (!ctx) {
        throw std::runtime_error("Failed to create message digest context");
    }

    // 初始化SHA256
    if (EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) != 1) {
        EVP_MD_CTX_free(ctx);
        throw std::runtime_error("Failed to initialize SHA256");
    }

    // 更新消息摘要
    if (EVP_DigestUpdate(ctx, password.c_str(), password.length()) != 1) {
        EVP_MD_CTX_free(ctx);
        throw std::runtime_error("Failed to update message digest");
    }

    // 完成哈希计算
    if (EVP_DigestFinal_ex(ctx, hash, &hash_len) != 1) {
        EVP_MD_CTX_free(ctx);
        throw std::runtime_error("Failed to finalize message digest");
    }

    // 释放上下文
    EVP_MD_CTX_free(ctx);

    // 将哈希值转换为十六进制字符串
    std::stringstream ss;
    for(unsigned int i = 0; i < hash_len; i++) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
    }
    return ss.str();
}

bool UserService::is_user_exist(const std::string& username) {
    return user_storage_->exists_by_username(username);
}

bool UserService::register_user(const std::string& username, const std::string& password) {
    if (is_user_exist(username)) {
        return false;
    }

    std::string password_hash = hash_password(password);

    storage::UserEntity user = {    
        .username = username,
        .password_hash = password_hash,
        // .created_at = std::chrono::system_clock::now(),
        // .updated_at = std::chrono::system_clock::now(),
        .is_online = false
    };

    return user_storage_->create_user(user);
}

bool UserService::login_user(const std::string& username, const std::string& password) {
    auto user = user_storage_->get_user_by_username(username);
        
    if (!user) {
        return false;
    }

    std::string password_hash = hash_password(password);

    if (user->password_hash != password_hash) {
        return false;
    }

    // 更新用户在线状态
    user->is_online = true;
    user_storage_->update_user(*user);

    // 生成会话token
    storage::UserSession session = {
        .username = username,
        .session_token = generate_session_token(),
        // .expires_at = std::chrono::system_clock::now() + std::chrono::hours(1)
    };

    // 存储会话token
    user_storage_->store_session(session);

    return true;
}

void UserService::logout_user(const std::string& username) {
    // 更新用户在线状态
    auto user = user_storage_->get_user_by_username(username);
    if (user) {
        user->is_online = false;
        user_storage_->update_user(*user);
    }
    
    // 删除会话
    user_storage_->delete_session(username);
}

bool UserService::verify_session(const std::string& username, const std::string& session_token) {
    auto session = user_storage_->get_session(username);
    if (!session) {
        return false;
    }

    return session->session_token == session_token;
    // && session->expires_at > std::chrono::system_clock::now();
}

bool UserService::is_user_online(const std::string& username) {
    try {
        auto user = user_storage_->get_user_by_username(username);
        return user && user->is_online;
    } catch (const std::exception& e) {
        // 记录错误日志
        Logger::error("Failed to check user online status: {}", e.what());
        return false;
    }
}

std::string UserService::generate_session_token() {
    // 生成一个随机的会话token
    unsigned char random[32];
    if (RAND_bytes(random, sizeof(random)) != 1) {
        throw std::runtime_error("Failed to generate random bytes");
    }
    
    std::stringstream ss;
    for(int i = 0; i < 32; i++) {
        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(random[i]);
    }
    return ss.str();
}

} // namespace service